/*
 * BlockedQ.cpp
 *
 *  Created on: 2013-11-12
 *      Author: jmes
 */

#include "BlockedQ.h"
#include <stdio.h>
#include <iostream>
#include "Process.h"
#include "PriorityQ.h"
#include <unistd.h>
#include "RuntimeParameters.h"

BlockedQ* BlockedQ::instance = NULL;

void BlockedQ::add(Process* p) {
	pthread_mutex_lock(&mutex);
	p->startTimer();
	usleep(MICROSECONDS_SLEEP_TIME);
	printf("BlockedQ: Process%d add to the blockQ\n", p->getProcessID());
	queue.push_back(p);
	pthread_cond_signal(&cond);
	pthread_mutex_unlock(&mutex);
}

BlockedQ* BlockedQ::getInstance() {
	if(instance == NULL) {
		instance = (new BlockedQ());
	}
	return instance;
}

void BlockedQ::decrementTimeOnOperations() {
	for (std::list<Process*>::iterator p = queue.begin(); p != queue.end(); p++) {
		// Remove time for the current operation
		(*p)->decreaseCurrentOperationTime();
		usleep(MICROSECONDS_SLEEP_TIME);
	}
}

void BlockedQ::checkForFinishedOperations() {
	std::list<Process*>::iterator queueIterator = queue.begin();

	while ( queueIterator != queue.end() ) {

		if ((*queueIterator)->getCurrentOperationTime() <= 0) {
			(*queueIterator)->setNextOperation();
			(*queueIterator)->stopTimer(Process::BlockedQ);
			printf("BlockedQ adding process%d to readyQ \n", (*queueIterator)->getProcessID());
			PriorityQ::getInstance()->add(&**queueIterator);
			queueIterator = queue.erase(queueIterator);
		} else {
			++queueIterator;
		}
	}
}

void BlockedQ::tick() {
	pthread_mutex_lock(&mutex);
	while(queue.empty()) {
		pthread_cond_wait(&cond, &mutex);
	}
	printf("BlockedQ: tick\n");
	decrementTimeOnOperations();
	checkForFinishedOperations();
	pthread_mutex_unlock(&mutex);
}


BlockedQ::BlockedQ() {
	queue = std::list<Process*>();
	cond = PTHREAD_COND_INITIALIZER;
	mutex = PTHREAD_MUTEX_INITIALIZER;

}
void BlockedQ::resetPriorityRuntime() {
	pthread_mutex_lock(&mutex);
	for (std::list<Process*>::iterator p = queue.begin(); p != queue.end(); p++) {
		(*p)->setPriorityRuntime(0);
	}
	pthread_mutex_unlock(&mutex);
}

BlockedQ::~BlockedQ() {
	// TODO Auto-generated destructor stub
}

